package dataStructure;

import dataStructure.interfaces.Chain;
import dataStructure.interfaces.Node;

import java.util.*;
import java.util.function.Consumer;

public class AbstractChain<E> implements Chain<E> {
    private final Node<E> first;
    private final Node<E> last;
    private Node<E> lastElement;
    private int size;

    AbstractChain(){
        first = SimpleNode.create(null);
        last = first.connectNext(SimpleNode.create(null));
        lastElement = null;
        size = 0;
    }

    Node<E> getFirstNode(){
        return first;
    }

    Node<E> getLastNode(){
        return last;
    }

    Node<E> getLastElement(){
        return lastElement;
    }

    void setLastElement(Node<E> lastElement){
        this.lastElement = lastElement;
    }

    void enlarge(){
        size++;
    }

    void reduce(){
        size--;
    }

    void enlarge(int amount){
        size+= amount;
    }

    @Override
    public boolean addFirst(E e) {
        Node<E> newNode = SimpleNode.create(e);
        getFirstNode().insertNext(newNode);

        if (getFirstNode() == getLastNode()){
            setLastElement(newNode);
        }

        enlarge();

        return true;
    }

    @Override
    public boolean addLast(E e) {
        Node<E> newNode = SimpleNode.create(e);
        getLastNode().insertNext(newNode);
        setLastElement(newNode);
        enlarge();

        return true;
    }

    @Override
    public boolean add(E position, E e) {
        return false;
    }

    @Override
    public boolean add(int index, E e) {
        return false;
    }

    @Override
    public boolean setFirst(E e) {
        return false;
    }

    @Override
    public boolean setLast(E e) {
        return false;
    }

    @Override
    public boolean set(E position, E e) {
        return false;
    }

    @Override
    public boolean set(int index, E e) {
        return false;
    }

    @Override
    public E removeFirst() {
        reduce();

        return getFirstNode().removeNext().getElement();
    }

    @Override
    public E removeLast() {

        return null;
    }

    @Override
    public E remove(E position) {
        return null;
    }

    @Override
    public E remove(int index) {
        return null;
    }

    @Override
    public E getFirst() {
        return null;
    }

    @Override
    public E getLast() {
        return getLastElement().getElement();
    }

    @Override
    public E get(int index) {
        return null;
    }

    @Override
    public boolean isEmpty() {
        return getLastElement() == null;
    }

    @Override
    public boolean contains(E e) {
        for (E element : this){
            if (Objects.equals(e, element)) return true;
        }

        return false;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public Chain<E> subChain(int start, int end) {
        return null;
    }

    @Override
    public Chain<E> subChain(int start) {
        return null;
    }

    @Override
    public E[] toArray() {
        return null;
    }

    @Override
    public List<E> toList(Class<? extends List> listClass) {
        return List.of();
    }

    @Override
    public String toString() {
        StringJoiner sj = new StringJoiner(", ", "[", "]");
        forEach(e -> sj.add(e.toString()));

        return sj.toString();
    }

    @Override
    public void forEach(Consumer<? super E> action) {
        getFirstNode().forEach(eNode -> {
            if (eNode != getFirstNode() && eNode != getLastNode()){
                action.accept(eNode.getElement());
            }
        });
    }

    @Override
    public Spliterator<E> spliterator() {
        return Chain.super.spliterator();
    }

    @Override
    public Iterator<E> iterator() {
        return null;
    }
}
